package main

import (
	"fmt"
	"reflect"
	"runtime"
)

/**
函数定义： func 方法名（参数名 参数类型）返回值 {}
1、函数可以存在多个返回值
2、如果返回值中某个返回值不需要使用，可以使用_
3、简单的函数式方法
4、可变参数的方法
*/

/**
定义一个计算的方法，返回值是 int
*/
func calc(num1, num2 int, oper string) int {
	switch oper {
	case "+":
		return num1 + num2
	case "-":
		return num1 - num2
	case "*":
		return num1 * num2
	case "/":
		return num1 / num2
	default:
		panic("unsupported oper " + oper)
	}
}

/**
函数返回多个返回值
*/
func div(num1, num2 int) (first, second int) {
	first = num1 / num2
	second = num1 % num2
	return first, second
}

/**
将函数中的错误返回出去
*/
func returnError(num int) (int, error) {
	if num > 10 {
		// 此处将错误返回出去
		return -1, fmt.Errorf("the num [%d] must less than 10", num)
	}
	return num + 1, nil
}

/**
测试函数式方法
funcMethod 中接收一个func,名字是operFun,接收2个int类型的值，并且返回int
*/
func funcMethod(operFun func(int, int) int, num1, num2 int) int {

	// 获取到方法 operFun 的方法名
	pointer := reflect.ValueOf(operFun).Pointer()
	methodName := runtime.FuncForPC(pointer).Name()

	fmt.Printf("调用函数[%s],参数为（%d,%d）", methodName, num1, num2)

	return operFun(num1, num2)
}

/**
可变变数方法
*/
func sum(nums ...int) int {
	ret := 0
	for i := range nums {
		ret += nums[i]
	}

	for index, value := range nums {
		fmt.Println(index, value)
	}

	return ret
}

func add(num1, num2 int) int {
	return sum(num1, num2)
}

func main() {

	println(calc(5, 4, "+"))

	// 此处只需要第一个返回值，因此第二个参数使用 _ 代替
	first, _ := div(6, 4)
	fmt.Println(first)

	_, err := returnError(50)
	if err != nil {
		fmt.Println(err)
	}

	// 函数式方法调用
	println(funcMethod(func(first int, second int) int {
		return first + second
	}, 3, 4))

	println(funcMethod(add, 3, 4))
}
